-- constants
MSG_LOGIN=1
MSG_KEEPALIVE=101
MSG_PROXYCOMMAND=102
MSG_UPDATEUSERLIST=201
MSG_RECEIVEDMESSAGE=202
MSG_AGENTLOGIN=2
MSG_PROXYTOCHATSERVERS=301
MSG_PROXYTOPHPSERVERS=401

JSON_MESSAGE_PROXY_DATA = 1
JSON_MESSAGE_UPDATE_USER_DATA = 2
JSON_MESSAGE_GET_USER_LIST = 3
JSON_MESSAGE_GET_USER_ROOM_LIST = 4
JSON_MESSAGE_EXIT_FROM_ROOM = 5
JSON_MESSAGE_LOGIN_SUCCESS = 6
JSON_MESSAGE_LOGIN_FAILED = 7


CHAT_SERVER_INTERNAL_ADDRESS="127.0.0.1:7658"
CHAT_SERVER_EXTERNAL_ADDRESS="127.0.0.1:7658"

AGENT_TEST_KEY="987654321"

ERROR_CODE_SUCCESS=0
ERROR_RESPONSE="{\"ecode\":3}"
ROOM_ID=1

EVENT_START=0
EVENT_CONNECTED=1
EVENT_RECEIVED_DATA=2

-- global variables
user1={id=1, nickname="t1"}
user2={id=2, nickname="t2"}
users = {user1}
current_user_id=1
current_step = 1
max_test_step = 1000

agent1={id=1}

-- arg functions
function agentConnect(args)
	common.warnlog("args._inarg: " .. args._inarg)
	networking.connect(args._inarg)
end

function agentLogin(args)
	local timestamp = os.time()
	local larg = {id=args._inarg.agent.id, rid=ROOM_ID, timestamp=timestamp}
	local b = false
	b,larg.sign = common.md5(larg.id .. larg.rid .. larg.timestamp .. AGENT_TEST_KEY)
	if b then
		networking.request(MSG_AGENTLOGIN, larg)
	else
		common.warnlog("common.md5 failed")
	end
end
function acceptLogin(args)
	-- Should proxy to PHP server
	-- In test mode return success.
	local data = common.parseJson(args.data)
	if data ~=nil and data.uid ~= nil and data.rid ~= nil then
		common.dumplog("accept user[" .. data.uid .. "] login room[" .. data.rid .. "]")
		local larg = {mid=JSON_MESSAGE_LOGIN_SUCCESS, uid=data.uid, rid=data.rid, data={uid=data.uid, exp1=math.random(1,1000), exp2=math.random(1,1000)}}
		networking.request(MSG_PROXYTOCHATSERVERS, larg)
	else
		common.warnlog("accept user login failed")
	end

end


-- test step defines
test_steps = {
	[10] = {name="agent connect", func=agentConnect, arg=CHAT_SERVER_INTERNAL_ADDRESS, next=20},
	[20] = {name="agent login", check={event=EVENT_CONNECTED}, func=agentLogin, arg={agent=agent1}, next=30},
	[30] = {name="agent login success", check={event=EVENT_RECEIVED_DATA, msgId=MSG_AGENTLOGIN}, 
			next=40},
	[40] = {name="accept client login", check={event=EVENT_RECEIVED_DATA, msgId=MSG_PROXYTOPHPSERVERS}, 
			func=acceptLogin, arg={}, next=40},
	[50] = {name="end", next=1000}
}

-- initialize test case
function init()
	print("init agent")
	common.dumplog("test common.dumplog")
	common.warnlog("test common.warnlog")
end

function deepcopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end

function call_test_func(func, arg)
	if type(arg) == "function" then
		func(arg())
	else
		func(arg)
	end
end

function do_test(args)
	local step = test_steps[current_step]
	local ret = 0
	local retData = ""
	while step == nil do
		current_step = current_step + 1
		if current_step > max_test_step then
			common.dumplog("test finished")
			return 0
		end
		step = test_steps[current_step]
	end
	
	common.dumplog("step[" .. current_step .. "] - " .. step.name .. " begin")
	if step.check ~= nil then
		common.dumplog("    checking")
		if step.check.event ~= nil then
			if step.check.event == args._event then
				common.dumplog("    check[Event] pass")
			else
				common.warnlog("    check[Event] failed")
			end
		end
		if step.check.msgId ~= nil then
			if step.check.msgId == args.msgId then
				common.dumplog("    check[msgId] pass")
			else
				common.warnlog("    check[msgId] failed")
			end
		end
		if step.check.ecode ~= nil then
			-- Todo: parse json
		end
	end
	
	if step.func ~= nil then
		if step.arg ~= nil then
			if args ~= nil then
				args._inarg = step.arg
			else
				args = {_inarg=step.arg}
			end
		end
		call_test_func(step.func, args)
		common.dumplog("    processing")
	end
	
	if step.next == nil or step.next >= max_test_step then
		common.dumplog("test case finished")
	else
		common.dumplog("step[" .. current_step .. "] - " .. step.name .. " end")
		current_step = step.next
	end
	return ret, retData
end

function start_test()
	common.dumplog("start test")
	current_step = 1
	local args = {_event=EVENT_START}
	do_test(args)
end	

function received_packet(args)
	args._event=EVENT_RECEIVED_DATA
	local ret, locat retData = do_test(args)
	if ret then
		return ret, retData
	else
		return ret, ERROR_RESPONSE
	end
end

function on_connected(args)
	local connId = args.connId
	common.dumplog("on_connected[" .. connId .. "]");
	do_test({_event=EVENT_CONNECTED})
	return true, error_code_success
end	

init()